#ifndef MQCLIENT_H
#define MQCLIENT_H

#include <QObject>
#include <QString>
#include <QByteArray>
#include <QDebug>
#include <QMutex>
#include <QTimer>
#include <QAtomicInt>
#include <QRunnable>
#include <QThreadPool>
#include "mqconfigmanager.h"
#include "mqconnectionpool.h"
#include <QDateTime>
#include <memory>

// RabbitMQ C客户端头文件
#include <amqp.h>
#include <amqp_tcp_socket.h>
#include <amqp_framing.h>

// 前向声明
class MQClient;

/**
 * @brief 消息结构体
 */
struct MQMessage {
    QString exchange;
    QString routingKey;
    QByteArray data;
    bool persistent;//发布消息持久化
    
    MQMessage() : persistent(true) {}
    MQMessage(const QString& ex, const QString& rk, const QByteArray& d, bool p = true)
        : exchange(ex), routingKey(rk), data(d), persistent(p) {}
};

/**
 * @brief MQ客户端发布任务类
 * 用于在线程池中异步执行消息发布操作
 */
class MQClientPublishTask : public QRunnable
{
public:
    /**
     * @brief 构造函数
     * @param client MQClient实例指针
     * @param exchange 交换机名称
     * @param routingKey 路由键
     * @param message 消息内容
     * @param persistent 是否持久化
     */
    MQClientPublishTask(MQClient* client, const QString& exchange, const QString& routingKey,
                       const QByteArray& message, bool persistent);
    
    /**
     * @brief 析构函数
     */
    ~MQClientPublishTask() = default;
    
    /**
     * @brief 执行任务
     */
    void run() override;
    
private:
    MQClient* m_client;         ///< MQClient实例指针
    QString m_exchange;         ///< 交换机名称
    QString m_routingKey;       ///< 路由键
    QByteArray m_message;       ///< 消息内容
    bool m_persistent;          ///< 是否持久化
};

/**
 * @brief RabbitMQ客户端类（线程安全单例）
 * 提供RabbitMQ的基本操作，包括连接、发布消息、消费消息等
 * 支持连接池、异步操作、自动重连等高级功能
 */
class MQClient : public QObject
{
    Q_OBJECT
    
public:
    /**
     * @brief 获取MQClient单例实例
     * @return MQClient实例指针
     */
    static MQClient* getInstance();
    
    /**
     * @brief 析构函数
     */
    ~MQClient();
    
    /**
     * @brief 使用配置文件连接到RabbitMQ服务器
     * @return 是否连接成功
     */
    bool connect();
    

    
    /**
     * @brief 断开连接
     */
    void disconnect();
    
    /**
     * @brief 启动自动重连
     */
    void startAutoReconnect();
    
    /**
     * @brief 停止自动重连
     */
    void stopAutoReconnect();
    
    /**
     * @brief 声明交换机
     * @param exchange 交换机名称
     * @param type 交换机类型 (direct, fanout, topic, headers)
     * @param durable 是否持久化
     * @return 是否成功
     */
    bool declareExchange(const QString &exchange, const QString &type = "direct", bool durable = true);
    
    /**
     * @brief 声明队列
     * @param queue 队列名称
     * @param durable 是否持久化
     * @param exclusive 是否排他
     * @param autoDelete 是否自动删除
     * @return 是否成功
     */
    bool declareQueue(const QString &queue, bool durable = true, bool exclusive = false, bool autoDelete = false);
    
    /**
     * @brief 绑定队列到交换机
     * @param queue 队列名称
     * @param exchange 交换机名称
     * @param routingKey 路由键
     * @return 是否成功
     */
    bool bindQueue(const QString &queue, const QString &exchange, const QString &routingKey);
    
    /**
     * @brief 解绑队列与交换机的绑定
     * @param queue 队列名称
     * @param exchange 交换机名称
     * @param routingKey 路由键
     * @return 是否成功
     */
    //配置界面选择不持久化队列，就不需要（暂留接口）
    bool unbindQueue(const QString &queue, const QString &exchange, const QString &routingKey);
    
    /**
     * @brief 发布消息到指定交换机和路由键
     * @param exchange 交换机名称
     * @param routingKey 路由键
     * @param message 消息内容
     * @param persistent 是否持久化消息
     * @return 是否发布成功
     */
    bool publishMessage(const QString &exchange, const QString &routingKey, const QByteArray &message, bool persistent = true);
    
    /**
     * @brief 使用默认业务配置发布消息（简化接口）
     * @param message 消息内容
     * @param persistent 是否持久化消息
     * @return 是否发布成功
     */
    bool publishMessage(const QByteArray &message, bool persistent = true);
    

    
    /**
     * @brief 异步发布消息到指定交换机和路由键
     * @param exchange 交换机名称
     * @param routingKey 路由键
     * @param message 消息内容
     * @param persistent 是否持久化消息
     * @return 是否成功加入异步队列
     */
    bool publishMessageAsync(const QString &exchange, const QString &routingKey, const QByteArray &message, bool persistent = true);
    
    /**
     * @brief 使用默认业务配置异步发布消息（简化接口）
     * @param message 消息内容
     * @param persistent 是否持久化消息
     * @return 是否成功加入异步队列
     */
    bool publishMessageAsync(const QByteArray &message, bool persistent = true);
    

    
    /**
     * @brief 从指定队列消费消息
     * @param queue 队列名称
     * @param autoAck 是否自动确认
     * @return 消息内容，如果没有消息则返回空
     */
    QByteArray consumeMessage(const QString &queue, bool autoAck = true);
    
    /**
     * @brief 使用默认业务配置从队列消费消息（简化接口）
     * @param autoAck 是否自动确认
     * @return 消息内容，如果没有消息则返回空
     */
    QByteArray consumeMessage(bool autoAck = true);
    
    /**
     * @brief 确认消息
     * @param deliveryTag 投递标签
     * @return 是否成功
     */
    bool ackMessage(uint64_t deliveryTag);
    
    /**
     * @brief 检查是否已连接
     * @return 是否已连接
     */
    bool isConnected() const;
    
    /**
     * @brief 获取连接池状态
     * @return 连接池状态字符串
     */
    QString getConnectionPoolStatus() const;
    
    /**
     * @brief 获取最后错误信息
     * @return 错误信息
     */
    QString getLastError() const;
    
    /**
     * @brief 初始化默认拓扑结构（交换机、队列、绑定）
     * @return 是否初始化成功
     */
    bool initializeDefaultTopology();
    
    /**
     * @brief 连接并初始化默认拓扑结构的便捷方法
     * @return 是否连接并初始化成功
     */
    bool connectAndInitialize();
    
    /**
     * @brief 设置业务配置（用于配置界面）
     * @param config 业务配置
     */
    void setBusinessConfig(const MQBusinessConfig& config);
    
    /**
     * @brief 获取当前业务配置
     * @return 业务配置
     */
    MQBusinessConfig getBusinessConfig() const;

signals:
    /**
     * @brief 连接状态改变信号
     * @param connected 是否已连接
     */
    void connectionChanged(bool connected);
    
    /**
     * @brief 错误信号
     * @param errorMsg 错误信息
     */
    void error(const QString &errorMsg);
    
    /**
     * @brief 重连成功信号
     */
    void reconnected();
    
    /**
     * @brief 重连失败信号
     * @param attempts 已尝试次数
     */
    void reconnectFailed(int attempts);
    
    /**
     * @brief 异步消息发布完成信号
     * @param success 成功数量
     * @param failed 失败数量
     */
    void asyncPublishCompleted(int success, int failed);
    
    /**
     * @brief 心跳检测信号
     * @param alive 连接是否存活
     */
    void heartbeatCheck(bool alive);

private:
    /**
     * @brief 私有构造函数（单例模式）
     * @param parent 父对象
     */
    explicit MQClient(QObject *parent = nullptr);
    
    /**
     * @brief 内部连接实现
     * @param config 连接配置
     * @return 是否连接成功
     */
    bool connectInternal(const MQConnectionConfig& config);
    
    /**
     * @brief 检查RPC回复
     * @param x RPC回复
     * @param context 上下文信息
     * @return 是否成功
     */
    bool checkRpcReply(amqp_rpc_reply_t x, const QString &context);
    
    /**
     * @brief 执行重连
     */
    void performReconnect();
    
    /**
     * @brief 心跳检测
     */
    void performHeartbeat();
    

    
private slots:
    /**
     * @brief 重连定时器超时处理
     */
    void onReconnectTimer();
    
    /**
     * @brief 心跳定时器超时处理
     */
    void onHeartbeatTimer();
    
    /**
     * @brief 配置改变处理
     */
    void onConfigChanged();

private:
    // 单例相关
    static MQClient* m_instance;        ///< 单例实例
    static QMutex m_instanceMutex;      ///< 实例创建互斥锁
    
    // 连接相关
    amqp_connection_state_t m_conn;     ///< RabbitMQ连接状态
    QAtomicInt m_connected;             ///< 是否已连接（原子操作）
    QString m_lastError;                ///< 最后一次错误信息
    mutable QMutex m_connectionMutex;   ///< 连接操作互斥锁
    
    // 配置管理
    // 配置管理器已移除，配置已硬编码到代码中
    
    // 连接池
    std::unique_ptr<MQConnectionPool> m_connectionPool; ///< 连接池
    
    // 注意：异步处理现在使用QThreadPool，不再需要专用的异步队列和工作线程
    
    // 重连机制
    QTimer* m_reconnectTimer;           ///< 重连定时器
    QAtomicInt m_reconnectAttempts;     ///< 重连尝试次数
    bool m_autoReconnectEnabled;        ///< 是否启用自动重连
    
    // 心跳检测
    QTimer* m_heartbeatTimer;           ///< 心跳定时器
    
    // 统计信息
    QAtomicInt m_publishedCount;        ///< 已发布消息数量
    QAtomicInt m_consumedCount;         ///< 已消费消息数量
    QAtomicInt m_errorCount;            ///< 错误计数
    
    // 业务配置
    MQBusinessConfig m_businessConfig;  ///< 业务配置（从配置界面设置）
    mutable QMutex m_businessConfigMutex; ///< 业务配置互斥锁
};





#endif // MQCLIENT_H
